﻿#pragma once

#include <learn/dll_ext.h>
#include <learn/geom/nurbs.h>
#include <learn/geom/vec.h>
#include <learn/math/integrator.h>

#include <Dense>
#include <Sparse>

namespace xi
{

namespace alg
{

using namespace xi::math;
using namespace xi::geom;

struct EXT_SYMBOL Alg_CoeffMatrix
{
    /**
     * @brief 计算曲线最小二乘系数矩阵
     *
     * @param[in] params
     * @param[in] knots
     * @param[in] p
     * @return Eigen::SparseMatrix<double>
     */
    static Eigen::SparseMatrix<double> curve_least_square(const std::vector<double> &params,
                                                          const std::vector<double> &knots, std::size_t p);

    /**
     * @brief 计算曲线拉伸-弯曲系数矩阵
     *
     * @param[in] knots
     * @param[in] p
     * @return std::array<Eigen::SparseMatrix<double>, 2>
     */
    static std::array<Eigen::SparseMatrix<double>, 2> curve_stretch_bending(const std::vector<double> &knots,
                                                                            std::size_t p);

    /**
     * @brief 计算曲面最小二乘系数矩阵
     *
     * @param[in] params
     * @param[in] uKnots
     * @param[in] vKnots
     * @param[in] p
     * @param[in] q
     * @return Eigen::SparseMatrix<double>
     */
    static Eigen::SparseMatrix<double> surface_least_square(const std::vector<Vec2> &params,
                                                            const std::vector<double> &uKnots,
                                                            const std::vector<double> &vKnots, std::size_t p,
                                                            std::size_t q);

    /**
     * @brief 计算曲面拉伸-弯曲系数矩阵
     *
     * @param[in] uKnots
     * @param[in] vKnots
     * @param[in] p
     * @param[in] q
     * @return std::array<Eigen::SparseMatrix<double>, 2>
     */
    static std::array<Eigen::SparseMatrix<double>, 2> surface_stretch_bending(const std::vector<double> &uKnots,
                                                                              const std::vector<double> &vKnots,
                                                                              std::size_t p, std::size_t q);
};

} // namespace alg

} // namespace xi